//	--------------------------------------------------------------------
//	Copyright(C) 2006,2007 Zhao Yukun. All rights reserved.
//	This file is a part of the Xeres system.
//	Xeres 2007
//	Contact : xeres.engine@gmail.com
//	$(reservedInfo)
//	$(reservedDeclaration)
//	--------------------------------------------------------------------
///	@file	<XFrameView.h>
///	@path	~/src/editor/wm/
///	@date	2008/05/20
///	@desc	Frame container of XForm.

#pragma once

#pragma message("Compiling XFrameView.h ...")

#include "editor/editor.h"

#include "lib/utilities/time.h"

#include "gui/composite/composition.h"
#include "gui/xgui/XForm.h"
#include "gui/xgui/XCtrls.h"
#include "gui/xgui/XCtrlsExt.h"
#include "gui/xgui/XEditCtrl.h"
#include "gui/xgui/XTagLayout.h"

#include "editor/xedit/XEditorFrame.h"

namespace xeres {

	/*! 
		\class	XFrameView
		\brief
	*/
	class XFrameView : public CWindowImpl< XFrameView > , public FrameBase
	{
	public:
		DECLARE_WND_CLASS( _T("xeres__XFrameView") )

		/// \ctor
		XFrameView( void ) {
			m_frame = new XEditorFrame( *this );
			m_insideLoop = false;
		}
		/// \dtor
		~XFrameView( void ) {
			m_frame->OnClose();
		}

		BOOL PreTranslateMessage(MSG* pMsg)
		{
			UNREFERENCED_PARAMETER( pMsg );
			return FALSE;
		}

		virtual RefWeak<IGuiForm> GetClientForm( void )
		{
			return m_frame;
		}

		virtual void AcquireUpdate( void )
		{
 			if( m_insideLoop )
			{
				Invalidate( FALSE );
 				return;
			}

			Layer& layer = m_frame->GetLayer();

			SIZE sz = { layer.GetWidth() , layer.GetHeight() };
			POINT pos = { m_pt.x , m_pt.y };
			POINT ptSource = {0};
			BLENDFUNCTION bf = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
			BOOL res = UpdateLayeredWindow( m_hWnd , NULL , &pos , &sz , layer.GetDC() , &ptSource , 0 , &bf , ULW_ALPHA );
			if( res == FALSE )
			{
				__win32_error( _S("AcquireUpdate Error: %s") );
			}
		}

		virtual void SetTitle( const wchar_t * title )
		{
			SetWindowText( title );
		}

		virtual HWND GetHwnd( void )
		{
			return m_hWnd;
		}

		BEGIN_MSG_MAP(XFrameView)
			MESSAGE_HANDLER(WM_ACTIVATE , OnActivate)
			MESSAGE_HANDLER(WM_CREATE, OnCreate)
			MESSAGE_HANDLER(WM_PAINT , OnPaint)
			MESSAGE_HANDLER(WM_SIZE , OnSize)
			MESSAGE_HANDLER(WM_ERASEBKGND , OnEraseBkgnd)
			MESSAGE_HANDLER(WM_MOVE , OnMove)
		// Dispatch message to XForm.
			{
				m_insideLoop = true;
				if( m_frame->DispatchMessages( m_hWnd , uMsg , wParam , lParam ) )
				{
					m_insideLoop = false;
					return TRUE; 
				}
				else
				{
					m_insideLoop = false;
					bHandled = FALSE;
				}
			}
		END_MSG_MAP()

		LRESULT OnActivate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) {
			// Dummy filter to refresh dispatcher states.
			m_frame->RefreshStates( m_hWnd );
			return S_OK;
		}
		LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) {

			// Setup ticking timer (30fps).
			this->SetTimer( TIMER_TICK , static_cast<int>( 1000.f / 30.f ) );

			m_frame->SetPlacement( Rect<int>(0,0,100,100) );

			CRect rc;
			this->GetWindowRect( &rc );
			m_frame->Resize( rc.Width() , rc.Height() );

			return S_OK;
		}
		LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) {
			CPaintDC dc( m_hWnd );

			AcquireUpdate();

// 			RECT client;
// 			this->GetClientRect( &client );
// 
// 			Layer& layer = m_frame->GetLayer();
// 
// 			int w = RectWidth( client );
// 			int h = RectHeight( client );
// 			dc.StretchDIBits( client.left , client.top , w , h ,
// 				0 , 0 , layer.GetWidth() , layer.GetHeight() , layer.GetPixel(0,0) , layer.GetBitmapInfo() ,
// 				DIB_RGB_COLORS , SRCCOPY );

			return S_OK;
		}
		LRESULT OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled ) {
			// re-create new painting buffer
			CRect rc;
			this->GetWindowRect( &rc );

			m_pt.x = rc.left;
			m_pt.y = rc.top;

			int w = rc.Width();
			int h = rc.Height();
			if( w == 0 || h == 0 )
				return S_OK;

			m_frame->Resize( w , h );
			AcquireUpdate();

			bHandled = FALSE;
			return S_OK;
		}
		LRESULT OnMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled ) {
			CRect rc;
			this->GetWindowRect( &rc );

			m_pt.x = rc.left;
			m_pt.y = rc.top;

			UpdateLayeredWindow(m_hWnd, NULL, &m_pt, NULL, NULL, NULL, 0, NULL, 0); 

			bHandled = FALSE;
			return S_OK;
		}
		LRESULT OnEraseBkgnd(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) {
			return S_OK;
		}

	private:

		//@ data
		Ref<XEditorFrame>		m_frame;
		CPoint					m_pt;
		bool					m_insideLoop;
	};

} // namespace xeres
